/*
 * 
 */
package fr.univtln.superplanning.api.study;

import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.TreeSet;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;

import fr.univtln.superplanning.api.actor.MainTeacher;
import fr.univtln.superplanning.api.actor.Student;

// TODO: Auto-generated Javadoc
/**
 * The Class Promotion.
 */
@Entity
@NamedQueries({
		@NamedQuery(name = "findPromotionByCode", query = "select p from Promotion p where p.code=:code"),
		@NamedQuery(name = "findAllPromotionCodes", query = "select p.code from Promotion p") })
public class Promotion {

	/** The id. */
	@Id
	@GeneratedValue
	private long id;

	/** The name. */
	@Column(unique = true, nullable = false)
	private String name;

	/** The code. */
	@Column(unique = true, nullable = false)
	private String code;

	/** The year. */
	@Column(nullable = false)
	private int year;

	/** The step. */
	@ManyToOne(cascade = CascadeType.ALL)
	private Step step;

	/** The students. */
	@OneToMany(cascade = CascadeType.ALL)
	private Set<Student> students = new HashSet<Student>();

	/** The student groups. */
	@OneToMany(cascade = CascadeType.ALL)
	private Set<StudentGroup> studentGroups = new TreeSet<StudentGroup>();
	// TODO: verify me
	/** The main teacher. */
	@OneToOne(cascade = CascadeType.ALL)
	private MainTeacher mainTeacher;

	/**
	 * Instantiates a new promotion.
	 */
	public Promotion() {
		// TODO Auto-generated constructor stub
	}

	/**
	 * Instantiates a new promotion.
	 * 
	 * @param name
	 *            the name
	 * @param code
	 *            the code
	 * @param year
	 *            the year
	 * @param step
	 *            the step
	 * @param mainTeacher
	 *            the main teacher
	 */
	public Promotion(String name, String code, int year, Step step, MainTeacher mainTeacher) {
		super();
		this.name = name;
		this.code = code;
		this.year = year;
		this.step = step;
		this.mainTeacher = mainTeacher;
	}

	/**
	 * Instantiates a new promotion.
	 * 
	 * @param name
	 *            the name
	 * @param code
	 *            the code
	 * @param year
	 *            the year
	 * @param students
	 *            the students
	 * @param step
	 *            the step
	 * @param mainTeacher
	 *            the main teacher
	 * @param studentGroups
	 *            the student groups
	 */
	public Promotion(String name, String code, int year, Set<Student> students, Step step,
			MainTeacher mainTeacher, Set<StudentGroup> studentGroups) {
		this(name, code, year, step, mainTeacher);
		this.students = students;
		this.studentGroups = studentGroups;
	}

	/**
	 * Gets the name.
	 * 
	 * @return the name
	 */
	public String getName() {
		return name;
	}

	/**
	 * Sets the name.
	 * 
	 * @param name
	 *            the new name
	 */
	public void setName(String name) {
		this.name = name;
	}

	/**
	 * Gets the year.
	 * 
	 * @return the year
	 */
	public int getYear() {
		return year;
	}

	/**
	 * Sets the year.
	 * 
	 * @param year
	 *            the new year
	 */
	public void setYear(int year) {
		this.year = year;
	}

	/**
	 * Gets the students.
	 * 
	 * @return the students
	 */
	public Set<Student> getStudents() {
		return students;
	}

	/**
	 * Sets the students.
	 * 
	 * @param students
	 *            the new students
	 */
	public void setStudents(Set<Student> students) {
		this.students = students;
	}

	/**
	 * Gets the student groups.
	 * 
	 * @return the student groups
	 */
	public Set<StudentGroup> getStudentGroups() {
		return studentGroups;
	}

	/**
	 * Sets the student groups.
	 * 
	 * @param studentGroups
	 *            the new student groups
	 */
	public void setStudentGroups(Set<StudentGroup> studentGroups) {
		this.studentGroups = studentGroups;
	}

	/**
	 * Gets the step.
	 * 
	 * @return the step
	 */
	public Step getStep() {
		return step;
	}

	/**
	 * Sets the step.
	 * 
	 * @param step
	 *            the new step
	 */
	public void setStep(Step step) {
		this.step = step;
	}

	/**
	 * Gets the code.
	 * 
	 * @return the code
	 */
	public String getCode() {
		return code;
	}

	/**
	 * Sets the code.
	 * 
	 * @param code
	 *            the new code
	 */
	public void setCode(String code) {
		this.code = code;
	}

	/**
	 * Gets the main teacher.
	 * 
	 * @return the main teacher
	 */
	public MainTeacher getMainTeacher() {
		return mainTeacher;
	}

	/**
	 * Sets the main teacher.
	 * 
	 * @param mainTeacher
	 *            the new main teacher
	 */
	public void setMainTeacher(MainTeacher mainTeacher) {
		this.mainTeacher = mainTeacher;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see java.lang.Object#hashCode()
	 */
	@Override
	public int hashCode() {
		return (step.getCode() + name + year).hashCode();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see java.lang.Object#equals(java.lang.Object)
	 */
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Promotion other = (Promotion) obj;
		if (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		if (step == null) {
			if (other.step != null)
				return false;
		} else if (!step.equals(other.step))
			return false;
		if (year != other.year)
			return false;
		return true;
	}

	/**
	 * Adds the.
	 * 
	 * @param arg0
	 *            the arg0
	 * @return true, if successful
	 */
	public boolean add(Student arg0) {
		return students.add(arg0);
	}

	/**
	 * Adds the all.
	 * 
	 * @param arg0
	 *            the arg0
	 * @return true, if successful
	 */
	public boolean addAll(Collection<? extends Student> arg0) {
		return students.addAll(arg0);
	}

	/**
	 * Clear.
	 */
	public void clear() {
		students.clear();
	}

	/**
	 * Contains.
	 * 
	 * @param arg0
	 *            the arg0
	 * @return true, if successful
	 */
	public boolean contains(Object arg0) {
		return students.contains(arg0);
	}

	/**
	 * Contains all.
	 * 
	 * @param arg0
	 *            the arg0
	 * @return true, if successful
	 */
	public boolean containsAll(Collection<?> arg0) {
		return students.containsAll(arg0);
	}

	/**
	 * Checks if is empty.
	 * 
	 * @return true, if is empty
	 */
	public boolean isEmpty() {
		return students.isEmpty();
	}

	/**
	 * Iterator.
	 * 
	 * @return the iterator
	 */
	public Iterator<Student> iterator() {
		return students.iterator();
	}

	/**
	 * Remove the.
	 * 
	 * @param arg0
	 *            the arg0
	 * @return true, if successful
	 */
	public boolean remove(Object arg0) {
		return students.remove(arg0);
	}

	/**
	 * Remove the all.
	 * 
	 * @param arg0
	 *            the arg0
	 * @return true, if successful
	 */
	public boolean removeAll(Collection<?> arg0) {
		return students.removeAll(arg0);
	}

	/**
	 * Retain all.
	 * 
	 * @param arg0
	 *            the arg0
	 * @return true, if successful
	 */
	public boolean retainAll(Collection<?> arg0) {
		return students.retainAll(arg0);
	}

	/**
	 * Size.
	 * 
	 * @return the int
	 */
	public int size() {
		return students.size();
	}

	/**
	 * To array.
	 * 
	 * @return the object[]
	 */
	public Object[] toArray() {
		return students.toArray();
	}

	/**
	 * To array.
	 * 
	 * @param <T>
	 *            the generic type
	 * @param arg0
	 *            the arg0
	 * @return the t[]
	 */
	public <T> T[] toArray(T[] arg0) {
		return students.toArray(arg0);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see java.lang.Object#toString()
	 */
	@Override
	public String toString() {
		return "Promotion [name=" + name + ", code=" + code + ", year=" + year + ", step=" + step
				+ ", students=" + students + ", studentGroups=" + studentGroups + ", mainTeacher="
				+ mainTeacher + "]";
	}

}
